from jeb.api import IScript
from jeb.api import JebInstance
from jeb.api.ast import Method
from jeb.api.ui import View
from jeb.api.ui import JavaView
from jeb.api.ui import CodePosition
from jeb.api.ui import AssemblyView
from org.eclipse.swt import SWT;
from org.eclipse.swt.events import SelectionAdapter;
from org.eclipse.swt.events import SelectionEvent;
from org.eclipse.swt.layout import GridData;
from org.eclipse.swt.layout import GridLayout;
from org.eclipse.swt.widgets import Display;
from org.eclipse.swt.widgets import Dialog
from org.eclipse.swt.widgets import Shell
from org.eclipse.swt.widgets import Table
from org.eclipse.swt.widgets import TableColumn
from org.eclipse.swt.widgets import TableItem
from org.eclipse.swt.widgets import Button
from org.eclipse.swt.widgets import Listener
from org.eclipse.swt.widgets import Event


from java.lang import Runnable

class ColumnName:
    NAME = 0
    SIGNATURE = 1
    name = {
        0 : "NAME",
        1 : "SIGNATURE"
    }

    @classmethod
    def values(cls):
        return [cls.NAME, cls.SIGNATURE]




class  LogPriority:
    ERROR=0
    WARN=1
    INFO=2
    DEBUG=3


class MethodsDialog(Dialog):
    # private final List methods;
    # private String response;

    def __init__(self, s, methods, instance):
        Dialog.__init__(self, s)
        self.response=None
        self.methods = methods
        self.instance = instance

    def open(self):
        parent = self.getParent()
        shell = Shell(parent, SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL)
        shell.setText("Methods")
        shell.setLayout(GridLayout(1, True))


        newTable = Table(shell, SWT.VIRTUAL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
        newTable.setLinesVisible(True);
        newTable.setHeaderVisible(True);
        gridData = GridData(SWT.FILL, SWT.FILL, True, True)
        newTable.setLayoutData(gridData);

        class SelectionListener(SelectionAdapter):
            def __init__(self, instance ,dlg):
                self.instance= instance
                self.dlg = dlg
			
            def pressKeyTab(self):
                event = Event();
                event.type = SWT.KeyDown;
                event.keyCode = ord(SWT.TAB);
                self.dlg.parent.getDisplay().post(event);

			
            def widgetSelected(self, selectionEvent):
                tableItem =  selectionEvent.item
                signature = tableItem.getText(ColumnName.SIGNATURE);
                self.instance.print("Method to jump: "+ signature);
                position = CodePosition(signature)
                ui = self.instance.getUI()
                assemblyView =  ui.getView(View.Type.ASSEMBLY)
                assemblyView.setCodePosition(position);
                ui.focusView(View.Type.ASSEMBLY);
                self.instance.decompileMethod(signature);
                self.pressKeyTab();
               # super.widgetSelected(selectionEvent);
                shell.dispose();

        newTable.addSelectionListener(SelectionListener(self.instance, self));

        for column in ColumnName.values():
            newColumn = TableColumn(newTable, SWT.NONE)
            newColumn.setText(ColumnName.name[column])

        for method in self.methods:
            newTableItem = TableItem(newTable, SWT.NONE)
            newTableItem.setText(ColumnName.SIGNATURE, method.getSignature())
            newTableItem.setText(ColumnName.NAME, method.getName())

        for cn in ColumnName.values():
            newTable.getColumn(cn).pack()

        buttonCancel = Button(shell, SWT.PUSH)
        buttonCancel.setText("CANCEL")

        class DisposeListener(Listener):
            def handleEvent(self, arg0):
                shell.dispose();
                response = None;

        buttonCancel.addListener(SWT.Selection, DisposeListener());


        shell.pack()
        shell.open()

        # display = parent.getDisplay()

        # while not shell.isDisposed():
        #     if not display.readAndDispatch():
        #         display.sleep()


        return self.response


class ListMethods(IScript):
    def run(self, jebInstance):
        self.instance = jebInstance
        self.ui = self.instance.getUI()
        self.jebDisplay = Display.getDefault()
        self.TAG="WinKaR"
        if not self.instance.isFileLoaded():
            e("File not loaded!")
            return

        class threadRunner(Runnable):
            def __init__(self, instance, jebDisplay, ui):
                self.instance = instance
                self.jebDisplay = jebDisplay
                self.ui = ui

            def getClassSignature(self, signature):
                return signature.split(";")[0].split("$")[0] + ";"

            def run(self):
                jebMainShell = self.jebDisplay.getShells()[0];
                javaView = self.ui.getView(View.Type.JAVA)
                signature = javaView.getCodePosition().getSignature();
                self.instance.print("Signature: " + signature);
                clsName = self.getClassSignature(signature);
                self.instance.print("Class Name: "+ clsName);
                for  method in self.instance.getDecompiledClassTree(clsName).getMethods():
                    self.instance.print("Method name: " + method.getName())

                md =  MethodsDialog(jebMainShell, self.instance.getDecompiledClassTree(clsName).getMethods(),
                                    self.instance);
                md.open();


        Display.getDefault().asyncExec(threadRunner(self.instance, self.jebDisplay, self.ui))



    



    def log(self, priority, message):
        if priority != None:
            instance.print(String.format("[%s] [%s]\t%s", self.TAG, priority.name(), message));
        else:
            instance.print(String.format("[%s]\t%s", self.TAG, message));

    # def d(String msg) { log(LogPriority.DEBUG, msg); }
    def  i(msg):
        self.log(LogPriority.INFO, msg)
    # private void w(String msg) { log(LogPriority.WARN, msg); }
    # private void e(String msg) { log(LogPriority.ERROR, msg); }
